﻿// ———————————————————————–
// <copyright file="HttpLoaderMain.cs" company="The MITRE Corporation">
//    Copyright (c) 2010 The MITRE Corporation. All rights reserved.
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//    http://www.apache.org/licenses/LICENSE-2.0
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
// </copyright>
// ———————————————————————–
/////////////////////////////////////////////////////////////////////////////////////////////////
// HttpLoaderMain.cs - Main Class for the HttpLoader WinForm
// Project: EDXLSharp_Tools - HttpLoader
//
// Language:    C#, .NET 4.0
// Platform:    Windows 7, VS 2010
// Author:      Don McGarry The MITRE Corporation
/////////////////////////////////////////////////////////////////////////////////////////////////

// Copyright (c) 2010 The MITRE Corporation. All rights reserved.
//
// NOTICE
// This software was produced for the U. S. Government
// under Contract No. FA8721-09-C-0001, and is
// subject to the Rights in Noncommercial Computer Software
// and Noncommercial Computer Software Documentation Clause
// (DFARS) 252.227-7014 (JUN 1995)
                
using System;
using System.ComponentModel;
using System.Configuration;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;
using EDXLSharp.EDXLDELib;

namespace HttpLoader
{
  /// <summary>
  /// Main Winform Class - Post Files to a server using HTTP POST
  /// </summary>
  public partial class HttpLoaderMain : Form
  {
    /// <summary>
    /// The URI of the Service to POST to
    /// </summary>
    private string postURI;

    /// <summary>
    /// The URI of the Service to pull xml from
    /// </summary>
    private string sourceURI;

    /// <summary>
    /// Base Directory where Data is stored
    /// </summary>
    private string basedirectory;

    /// <summary>
    /// Initializes a new instance of the HttpLoaderMain class
    /// Default Ctor
    /// </summary>
    public HttpLoaderMain()
    {
      this.InitializeComponent();
      foreach (string key in ConfigurationManager.AppSettings)
      {
        switch (key)
        {
          case "PostURI":
            this.postURI = ConfigurationManager.AppSettings[key];
            this.postURItb.Text = this.postURI;
            break;
          case "SourceURI":
            this.sourceURI = ConfigurationManager.AppSettings[key];
            this.sourceURItb.Text = this.sourceURI;
            break;
          case "DataDirectory":
            this.basedirectory = ConfigurationManager.AppSettings[key];
            this.dataDirtb.Text = this.basedirectory;
            break;
          default:
            break;
        }
      }

      this.backgroundWorker1.WorkerReportsProgress = true;
    }

    /// <summary>
    /// Delegate Callback to Report Progress
    /// </summary>
    /// <param name="TotalFiles">Total Number of Files to POST</param>
    /// <param name="FilesSent">Number of Files POSTED</param>
    internal delegate void ShowSendProgress(int TotalFiles, int FilesSent);

    #region Button Handlers

    /// <summary>
    /// Handler for Data Directory Browse Button
    /// </summary>
    /// <param name="sender">object calling</param>
    /// <param name="e">Button Event Args</param>
    private void DataDirBrowseButt_Click(object sender, EventArgs e)
    {
      if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
      {
        this.dataDirtb.Text = this.folderBrowserDialog1.SelectedPath;
      }
    }

    /// <summary>
    /// Handler for Post Directory Browse Button
    /// </summary>
    /// <param name="sender">object calling</param>
    /// <param name="e">Button Event Args</param>
    private void PostDirBrowseButt_Click(object sender, EventArgs e)
    {
      if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
      {
        this.postDirtb.Text = this.folderBrowserDialog1.SelectedPath;
      }
    }

    /// <summary>
    /// Handler for Post Durectory Post Button
    /// </summary>
    /// <param name="sender">object calling</param>
    /// <param name="e">Button Event Args</param>
    private void PostDirPostButt_Click(object sender, EventArgs e)
    {
      this.postURI = this.postURItb.Text;
      this.basedirectory = this.postDirtb.Text;
      try
      {
        SenderArgs sargs = new SenderArgs { Directory = this.basedirectory, FilePrefix = String.Empty };
        this.backgroundWorker1.RunWorkerAsync(sargs);
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.ToString() + "\r\n\r\n" + ex.StackTrace);
      }
    }

    /// <summary>
    /// Handler for Save Settings Button
    /// </summary>
    /// <param name="sender">object calling</param>
    /// <param name="e">Button Event Args</param>
    private void SaveButt_Click(object sender, EventArgs e)
    {
      Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
      config.AppSettings.Settings["PostURI"].Value = this.postURItb.Text;
      config.AppSettings.Settings["SourceURI"].Value = this.sourceURItb.Text;
      config.AppSettings.Settings["DataDirectory"].Value = this.dataDirtb.Text;
      config.Save(ConfigurationSaveMode.Modified);
      ConfigurationManager.RefreshSection("appSettings");
    }

    /// <summary>
    /// Handler for Post Button for the Combobox
    /// </summary>
    /// <param name="sender">object calling</param>
    /// <param name="e">Button Event Args</param>
    private void PostComboPostButt_Click(object sender, EventArgs e)
    {
      string directory = String.Empty;
      string fileprefix = String.Empty;
      SenderArgs sargs;
      this.postURI = this.postURItb.Text;
      this.basedirectory = this.dataDirtb.Text;

      switch (this.dataComboSelect.Text)
      {
        case "CAP":
          directory = this.basedirectory + "CAP";
          fileprefix = "CAP";
          break;
        case "CAP-ICBRNE":
          directory = this.basedirectory + "SPAWAR";
          fileprefix = "CAP";
          break;
        case "CoT Vehicle":
          directory = this.basedirectory + "CoTVehicle";
          fileprefix = String.Empty;
          break;
        case "HAVE":
          directory = this.basedirectory + "HAVE";
          fileprefix = "Wrapped";
          break;
        case "HAVE-LAFD":
          directory = this.basedirectory + "LAFDHAVE";
          fileprefix = "LAFDHAVE";
          break;
        case "RM":
          directory = this.basedirectory + "RM";
          fileprefix = "RM";
          break;
        case "RM Update":
          directory = this.basedirectory + "Update";
          fileprefix = "RM";
          break;
        case "RM-OfferUnsolicitedResource":
          directory = this.basedirectory + this.dataComboSelect.Text;
          fileprefix = this.dataComboSelect.Text;
          break;
        case "RM-RequestResource":
          directory = this.basedirectory + this.dataComboSelect.Text;
          fileprefix = this.dataComboSelect.Text;
          break;
        case "RM-RequisitionResource":
          directory = this.basedirectory + this.dataComboSelect.Text;
          fileprefix = this.dataComboSelect.Text;
          break;
        case "SitRep":
          directory = this.basedirectory + "SitRep";
          fileprefix = "SitRep";
          break;
        case "TEP":
          directory = this.basedirectory + "TEP";
          fileprefix = "TEP";
          break;
        default:
          MessageBox.Show("Unknown selection: " + this.dataComboSelect.Text + "\nTry Again...");
          return;
      }

      try
      {
        sargs = new SenderArgs { Directory = directory, FilePrefix = fileprefix };
        this.backgroundWorker1.RunWorkerAsync(sargs);
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.ToString() + "\r\n\r\n" + ex.StackTrace);
      }
    }

    /// <summary>
    /// Handler for Post Button for the Textbox
    /// </summary>
    /// <param name="sender">object calling</param>
    /// <param name="e">Button Event Args</param>
    private void PostTextButt_Click(object sender, EventArgs e)
    {
      this.postURI = this.postURItb.Text;
      EDXLDE deobj = new EDXLDE();
      HttpWebRequest request;
      HttpWebResponse resp;
      string requesturi = this.postURI;
      try
      {
        deobj.ReadXML(this.postText.Text);
        request = (HttpWebRequest)WebRequest.Create(requesturi);
        string s = this.postText.Text;
        s = s.Replace("<?xml version=\"1.0\" encoding=\"utf-16\" standalone=\"no\"?>\r\n", String.Empty);
        request.KeepAlive = true;
        request.Method = "POST";
        request.ContentType = "text/xml";
        request.AllowAutoRedirect = true;
        request.ContentLength = Encoding.UTF8.GetByteCount(s);
        this.SetBody(request, s);
        resp = (HttpWebResponse)request.GetResponse();
        resp.Close();
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.ToString() + "\r\n\r\n" + ex.StackTrace);
      }

      MessageBox.Show("Done");
    }

    #endregion

    #region Background Worker Events

    /// <summary>
    /// This method receives the DoWork event of the background worker thread and calls SendFile.
    /// </summary>
    /// <param name="sender">object calling</param>
    /// <param name="e">Work Event Args</param>
    private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
      // Get the BackgroundWorker that raised this event.
      BackgroundWorker worker = sender as BackgroundWorker;
      SenderArgs sargs = e.Argument as SenderArgs;
      this.SendFile(sargs.Directory, sargs.FilePrefix, worker, e);
    }

    /// <summary>
    /// This method receives the ProgressChanged event of the background worker thread and updates
    /// the UI progress bar.
    /// </summary>
    /// <param name="sender">object calling</param>
    /// <param name="e">Process Changed Event Args</param>
    private void BackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
      if (e.ProgressPercentage <= 100)
      {
        this.progressBar1.Value = e.ProgressPercentage;
      }
    }

    /// <summary>
    /// This method receives the RunWorkerCompeleted event of the background worker thread
    /// and notifies the user that the current operation has finished in some fashion.
    /// </summary>
    /// <param name="sender">object calling</param>
    /// <param name="e">Worker Completed Event Args</param>
    private void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
      if (e.Error != null)
      {
        MessageBox.Show("The following error has occurred during the current operation: " + e.Error.Message, "Send Files", MessageBoxButtons.OK, MessageBoxIcon.Error);
      }
      else if (e.Cancelled)
      {
        MessageBox.Show("The current operation has been cancelled", "Send Files", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
      }
      else
      {
        MessageBox.Show("The current operation has completed", "Send Files", MessageBoxButtons.OK, MessageBoxIcon.Information);
      }

      this.progressBar1.Value = 0;
    }

    #endregion

    #region HTTP POST Functions

    /// <summary>
    /// Posts a set of files to the server using a Background Worker
    /// </summary>
    /// <param name="directory">Directory to load files from</param>
    /// <param name="fileprefix">Prefix search string</param>
    /// <param name="worker">Worker to do work</param>
    /// <param name="e">Worker event args</param>
    private void SendFile(string directory, string fileprefix, BackgroundWorker worker, DoWorkEventArgs e)
    {
      if (worker.CancellationPending)
      {
        e.Cancel = true;
      }
      else
      {
        if (Directory.Exists(directory))
        {
          
          


            string[] files = Directory.GetFiles(directory, fileprefix + "*" + "*.xml");
            StreamReader sr;
            HttpWebRequest request;
            HttpWebResponse resp;
            string requesturi = this.postURI;

            int fileCount = files.Length;
            if (this.TimesOneThousandCopies.Checked)
            {
              fileCount *= 1000;
            }
            int ifile = 0;

            foreach (string file in files)
            {
              sr = new StreamReader(file);

              string s = sr.ReadToEnd();
              s = s.Replace("<?xml version=\"1.0\" encoding=\"utf-16\" standalone=\"no\"?>\r\n", String.Empty);

              int multiplierFactor = 1;
              if (this.TimesOneThousandCopies.Checked)
              {
                multiplierFactor = 1000;
              }
              for (int multiplier = 0; multiplier < multiplierFactor; multiplier++)
              {
                request = (HttpWebRequest)WebRequest.Create(requesturi);
                request.KeepAlive = true;
                request.Method = "POST";
                request.ContentType = "text/xml";
                request.AllowAutoRedirect = true;
                request.ContentLength = Encoding.UTF8.GetByteCount(s);
                this.SetBody(request, s);

                resp = null;
                try
                {
                  resp = (HttpWebResponse)request.GetResponse();
                  resp.Close();
                }
                catch (WebException exception)
                {
                  StreamReader streamReader = new StreamReader(exception.Response.GetResponseStream(), true);
                  string message = streamReader.ReadToEnd();

                  MessageBox.Show(((HttpWebResponse)exception.Response).StatusDescription + "\n\n" + message);
                }
                finally
                {
                  sr.Close();
                }




                if (this.checkDoOne.Checked)
                {
                  break;
                }

                ifile++;

                int percentComplete = (int)((float)ifile / (float)fileCount * 100);

                worker.ReportProgress(percentComplete);
              }
              //MessageBox.Show("OK");
            }
         
        }
        else
        {
          throw new System.IO.DirectoryNotFoundException("Directory does not exist, " + directory);
        }
      }
    }

    /// <summary>
    /// Function to perform HTTP POST
    /// </summary>
    /// <param name="request">Pending Web Request</param>
    /// <param name="requestBody">Body to POST</param>
    private void SetBody(HttpWebRequest request, string requestBody)
    {
      if (requestBody.Length > 0)
      {
        Stream requestStream = request.GetRequestStream();
        StreamWriter writer = new StreamWriter(requestStream);
        writer.AutoFlush = true;
        writer.Write(requestBody);
        writer.Flush();
        writer.Close();
        requestStream.Flush();
        requestStream.Close();
      }
    }

    #endregion

    private void label6_Click(object sender, EventArgs e)
    {

    }

    private void postURItb_TextChanged(object sender, EventArgs e)
    {

    }

    private void PostXMLFromOtherServer_Click(object sender, EventArgs e)
    {
        
    }
  }
}
